//////////////////////////////////////////////////////////////////////
//
//  CryEngine Source code
//	
//	File: AnimationManager.h
//  Implementation of Animation Manager.h
//
//	History:
//	January 12, 2005: Created by Ivo Herzeg <ivo@crytek.de>
//
//////////////////////////////////////////////////////////////////////

#ifndef _CRYTEK_GAHLMG_
#define _CRYTEK_GAHLMG_

#include "GlobalAnimationHeader.h"
#include <NameCRCHelper.h>
#include <PoolAllocator.h>
extern stl::PoolAllocatorNoMT<sizeof(SAnimationSelectionProperties)> *g_Alloc_AnimSelectProps;
struct ModelAnimationHeader;
class CSkeletonAnim;

struct BSAnimationLMG
{
	BSAnimationLMG()
	{
		m_qVelocity	=	Vec3(0,0,0);
		m_Position	=	Vec3(0,0,0);
	}

	Vec3  m_qVelocity;         //asset-feature: the velocity vector for this asset
	Vec3  m_Position;
	SCRCName m_animName;

	void GetMemoryUsage( ICrySizer *pSizer ) const
	{
#if STORE_CRCNAME_STRINGS
		pSizer->AddObject(m_animName.m_name);
#endif 
	}
};



struct BSBlendable
{
	BSBlendable()
	{
		num=0;
		idx0=-1;
		idx1=-1;
		idx2=-1;
		idx3=-1;
		idx4=-1;
		idx5=-1;
		idx6=-1;
		idx7=-1;
	}

	uint32 num; uint8 idx0,idx1,idx2,idx3,idx4,idx5,idx6,idx7;

	void GetMemoryUsage( ICrySizer *pSizer ) const
	{
	}
};

struct BSParameter
{
	BSParameter()
	{
		m_Para=Vec4(0,0,0,0); //4D will be the maximum
		i0=0;	w0=0.0f;
		i1=0;	w1=0.0f;
	}

	Vec4 m_Para;
	uint32 i0;	f32 w0;
	uint32 i1;	f32 w1;

	void GetMemoryUsage( ICrySizer *pSizer ) const
	{
	}
};

struct VExample1D 
{	
	uint8 i0,i1;
	f32	w0,w1; 
};

struct VExample2D 
{	
	uint8 i0,i1,i2,i3;
	f32	w0,w1,w2,w3; 
};

struct VExample3D 
{	
	uint8 i0,i1,i2,i3,i4,i5,i6,i7;
	f32	w0,w1,w2,w3,w4,w5,w6,w7; 
};

//////////////////////////////////////////////////////////////////////////
// this is the animation information on the module level (not on the per-model level)
// it doesn't know the name of the animation (which is model-specific), but does know the file name
// Implements some services for bone binding and ref counting
struct GlobalAnimationHeaderLMG : public GlobalAnimationHeader
{
	friend class CAnimationManager;
	friend class CAnimationSet;

	GlobalAnimationHeaderLMG ()
	{
		m_FilePathCRC32		=	0;
		m_nRef_by_Model		= 0;
		m_nBlendCodeLMG		=	0;
		m_nTouchedCounter	= 0;
		m_nInitialized		= 0;  //we will use this for run-time initialisation
		m_nSelectionCapsCode	=	0;
		m_pSelectionProperties = NULL;
		m_Dimensions=0;
		m_min0=0.0f; m_max0=0.0f; m_scale0=1.0f; m_cells0=3;
		m_min1=0.0f; m_max1=0.0f; m_scale1=1.0f; m_cells1=3;
		m_min2=0.0f; m_max2=0.0f; m_scale2=1.0f; m_cells2=3;
		m_min3=0.0f; m_max3=0.0f; m_scale3=1.0f; m_cells3=3;
		m_fThreshold = -99999.0f;
		m_fDesiredLocalLocationLookaheadTime=0.2f;	
	}

	bool Export2HTR(const char* szAnimationName, const char* savePath, const CCharacterModel* pModel, CSkeletonAnim* pSkeletonAnim);

	const char* GetFilePath() const {	return m_FilePath.c_str(); };
	int GetFilePathCRC32() { return m_FilePathCRC32; }
	void SetFilePath(const string& name) 
	{ 
		m_FilePath = name; 
#ifdef _USE_LOWERCASE
		assert (name.size() < MAX_STATIC_CHARS);
		char pStringArray[MAX_STATIC_CHARS];
		NameCRCHelper::MakeLowercase(pStringArray, name.c_str());
		m_FilePathCRC32 = gEnv->pSystem->GetCrc32Gen()->GetCRC32(pStringArray); 
#else
		m_FilePathCRC32 = gEnv->pSystem->GetCrc32Gen()->GetCRC32(name.c_str()); 
#endif
	};


	void AllocateAnimSelectProps()
	{
		assert(m_pSelectionProperties == NULL);
		m_pSelectionProperties = (SAnimationSelectionProperties*)g_Alloc_AnimSelectProps->Allocate();
		m_pSelectionProperties->init();
	}

	virtual ~GlobalAnimationHeaderLMG()
	{
		if (m_pSelectionProperties != NULL)
			g_Alloc_AnimSelectProps->Deallocate(m_pSelectionProperties);
	};


	void AddRef()
	{
		++m_nRef_by_Model;
	}

	void Release()
	{
		if (!--m_nRef_by_Model)
		{
			m_arrBSAnimations.clear();	// nobody uses the blend-spaces; clean them up.
		}
	}

	ILINE uint32 IsAssetLoaded() const { return 1; }
	ILINE uint32 IsAssetOnDemand() const { return 0; }

	size_t SizeOfLMG()const
	{
		size_t nSize = sizeof(*this);
		size_t nTemp00 = m_FilePath.capacity();		nSize += nTemp00;
		nSize += m_arrBSAnimations.get_alloc_size();

		nSize += m_AnimEventsLMG.get_alloc_size();
		uint32 numEvents = m_AnimEventsLMG.size();
		for (uint32 i=0; i<numEvents; i++)
		{
			nSize += m_AnimEventsLMG[i].m_strModelName.capacity();
			nSize += m_AnimEventsLMG[i].m_strEventName.capacity();
			nSize += m_AnimEventsLMG[i].m_strCustomParameter.capacity();
			nSize += m_AnimEventsLMG[i].m_strBoneName.capacity();
		}

		size_t s = m_strSpliceAnim.size();
		nSize += m_strSpliceAnim.capacity() * sizeof(SCRCName);

		nSize += m_jointList.get_alloc_size();

		return nSize;
	}

	void GetMemoryUsage(ICrySizer *pSizer) const
	{
		pSizer->AddObject( m_FilePath );

		pSizer->AddObject( m_arrBSAnimations );
		pSizer->AddObject( m_AnimEventsLMG );		
		pSizer->AddObject( m_strSpliceAnim );
		pSizer->AddObject( m_jointList );		
	}

public:
	string m_FilePath;								//path-name - unique per-model
	uint32 m_FilePathCRC32;						//hash value for searching animations
	SAnimationSelectionProperties* m_pSelectionProperties;
	DynArray<SCRCName> m_strSpliceAnim;
	DynArray<AnimEvents> m_AnimEventsLMG;
	DynArray<uint32> m_jointList;

	DynArray<BSAnimationLMG> m_arrBSAnimations;
	DynArray<BSParameter> m_arrParameter;
	DynArray<BSBlendable> m_arrBSAnnotations1;
	DynArray<BSBlendable> m_arrBSAnnotations2;

	f32 m_fDesiredLocalLocationLookaheadTime;	
	uint32 m_Dimensions;
	string m_strParaName0;	f32 m_min0,m_max0,m_scale0; uint32 m_cells0;
	string m_strParaName1;	f32 m_min1,m_max1,m_scale1; uint32 m_cells1;
	string m_strParaName2;	f32 m_min2,m_max2,m_scale2; uint32 m_cells2;
	string m_strParaName3;	f32 m_min3,m_max3,m_scale3; uint32 m_cells3;
	DynArray<VExample1D> m_ParaGrid1D;
	DynArray<VExample2D> m_ParaGrid2D;
	DynArray<VExample3D> m_ParaGrid3D_1;
	DynArray<VExample3D> m_ParaGrid3D_2;

	// the number of referrers to this global animation record (doesn't matter if the controllers are currently loaded)
	int32		m_nRef_by_Model;
	uint32	m_nTouchedCounter;
	uint32	m_nInitialized;
	f32			m_fThreshold;

	uint32	m_nBlendCodeLMG;
	uint32	m_nSelectionCapsCode;
} _ALIGN(16);


#endif
